/* 
参考链接：https://juejin.cn/post/7029614824963178526
bind方法性质：
1.调用bind会返回一个新函数
2.分段接收参数
3.改变this指向
4.返回的新函数可以使用new标识符
*/

Function.prototype.myBind = function (newThis) {
  let _this = this;
  //FIXME: console.log(arguments); // [Arguments] { '0': null, '1': 'Tom' }
  // 获取第一个参数之后的所有参数(利用arguments)
  let outArg = Array.prototype.slice.call(arguments, 1);
  //FIXME: console.log(outArg); // ['Tom']
  let fn = function (...args) {
    // args获取使用myBind之后返回函数的参数
    //FIXME: console.log(args);  // [2021]
    // 利用apply改变this指向
    _this.apply(this instanceof fn ? this : newThis, [...outArg, ...args]); // apply接收的是this以及一个参数数组
    //FIXME: console.log(this);
  };
  fn.prototype = this.prototype;
  return fn;
};

let obj = {
  month: 11,
};

function demo(name, year) {
  console.log(`姓名：${name} 年份：${year}  月：${this.month}。`);
}
demo.prototype.sayHello  =function(){
  console.log('hello');
}

let t = demo.myBind(obj, "Tom");
let a = new t();  // undefined
console.log(a);
a.sayHello() // hello
